package com.traffic.util;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.traffic.constant.Const;
import com.traffic.entity.Admin;
import com.traffic.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * Created by IntelliJ IDEA.
 * User: KingRainGrey
 * Date: 2020/9/4
 */
@Component
@Slf4j
public class JwtUtil {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static final String TOKEN_SECRET = "8cb65c9044364c46909202e86c2ba42a";
    private static final String ADMIN_SECRET = "mZmU3lzI8wiYWNjb3VudCI6IjEyMzQ1N";
    private static final String ISSUER = "trafficSys";
    private static final String TAG = "Token";

    public static String sign(User user) {
        String token = null;
        try {
            token = JWT.create()
                    .withIssuer(ISSUER)
                    .withClaim("random", IdUtil.fastSimpleUUID())
                    .withClaim("account", user.getAccount())
                    .sign(Algorithm.HMAC256(TOKEN_SECRET));
        } catch (Exception e) {
            log.error("Token生成失败.");
        }
        return token;
    }

    public static String sign(Admin admin) {
        String token = null;
        try {
            token = JWT.create()
                    .withIssuer(ISSUER)
                    .withClaim("random", IdUtil.fastSimpleUUID())
                    .withClaim("account", admin.getAccount())
                    .sign(Algorithm.HMAC256(ADMIN_SECRET));
        } catch (Exception e) {
            log.error("Token生成失败.");
        }
        return token;
    }

    // token正确性验证 用户
    public boolean verify(String token) {
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer(ISSUER).build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (Exception e) {
            log.info("Token验证不通过.");
            return false;
        }
    }

    // token正确性验证 管理员
    public boolean verifyAdmin(String token) {
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(ADMIN_SECRET)).withIssuer(ISSUER).build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (Exception e) {
            log.info("Token验证不通过.");
            return false;
        }
    }

    // 获取用户
    public String getAccountUser(String token) {
        return get(token, TOKEN_SECRET);
    }

    // 获取管理员
    public String getAccountAdmin(String token) {
        return get(token, ADMIN_SECRET);
    }

    // 获取账户信息
    public String get(String token, String secret) {
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret)).withIssuer(ISSUER).build();
            DecodedJWT jwt = verifier.verify(token);
            return jwt.getClaim("account").asString();
        } catch (Exception e) {
            log.info("Token解析失败.");
        }
        return null;
    }

    // 从token中获取账户信息 0管理员 1用户
    public String getAccount(Integer type) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
        String token = request.getHeader(TAG);
        if (type == 0) {
            return getAccountAdmin(token);
        }else if (type == 1) {
            return getAccountUser(token);
        }
        return null;
    }

    // 用户token检查
    public boolean check(String account) {
        String token = getToken();
        log.debug("【传入Token】:{}", token);
        if (ObjectUtil.isNull(token)) {
            return false;
        }
        if (verify(token) == false) {
            return false;
        }
        String redisToken = stringRedisTemplate.opsForValue().get(Const.TOKEN_PREFIX + account);
        log.debug("【TokenKey】:{}", account);
        log.debug("【存储Token】:{}", redisToken);
        if (StrUtil.equals(token, redisToken)) {
            return true;
        }
        return false;
    }

    // 管理员token检查
    public boolean confirm(String account) {
        String token = getToken();
        log.debug("【传入Token】:{}", token);
        if (ObjectUtil.isNull(token)) {
            return false;
        }
        if (verifyAdmin(token) == false) {
            return false;
        }
        String redisToken = stringRedisTemplate.opsForValue().get(Const.TOKEN_PREFIX + account);
        log.debug("【TokenKey】:{}", account);
        log.debug("【存储Token】:{}", redisToken);
        if (StrUtil.equals(token, redisToken)) {
            return true;
        }
        return false;
    }

    public String getToken() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
        String token = request.getHeader(TAG);
        return token;
    }
}
